package com.sxhuayuan.parking.task;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.sxhuayuan.parking.entity.Agent;
import com.sxhuayuan.parking.entity.ParkingLot;
import com.sxhuayuan.parking.entity.ProfitStatistics;
import com.sxhuayuan.parking.service.AgentRelationService;
import com.sxhuayuan.parking.service.AgentService;
import com.sxhuayuan.parking.service.OrderService;
import com.sxhuayuan.parking.service.ParkingLotService;
import com.sxhuayuan.parking.service.ProfitStatisticsService;
import com.sxhuayuan.parking.service.RedisService;
import com.sxhuayuan.parking.utils.DateUtils;
import com.sxhuayuan.parking.utils.SettingUtils;
import com.sxhuayuan.parking.utils.SpringUtils;

public class ProfitStatisticsTask implements Runnable {

	Logger log = LoggerFactory.getLogger(ProfitStatisticsTask.class);

	RedisService redisService;
	OrderService orderService;
	AgentService agentService;
	AgentRelationService agentRelationService;
	ProfitStatisticsService profitStatisticsService;
	ParkingLotService parkingLotService;

	private final static BigDecimal HUNDRED = new BigDecimal(100);
	private final static BigDecimal ZERO = BigDecimal.ZERO;

	// 临时存储所有代理的流水统计
	private Map<String, ProfitStatistics> map;
	private LocalDate date;

	public ProfitStatisticsTask(LocalDate date) {
		super();
		this.date = date;
	}

	@Override
	public void run() {
		String uuid = RandomStringUtils.randomAlphabetic(8);
		log.debug("[{}]分润统计线程开始", uuid);
		init();
		agentProfitStatisticsJob();
		log.debug("[{}]分润统计线程结束", uuid);
	}

	private void init() {
		redisService = SpringUtils.getBean("redisServiceImpl", RedisService.class);
		orderService = SpringUtils.getBean("orderServiceImpl", OrderService.class);
		agentService = SpringUtils.getBean("agentServiceImpl", AgentService.class);
		agentRelationService = SpringUtils.getBean("agentRelationServiceImpl", AgentRelationService.class);
		profitStatisticsService = SpringUtils.getBean("profitStatisticsServiceImpl", ProfitStatisticsService.class);
		parkingLotService = SpringUtils.getBean("parkingLotServiceImpl", ParkingLotService.class);
	}

	/**
	 * 每天00:00:00 统计前一天代理分润
	 */
	public void agentProfitStatisticsJob() {
		log.debug("统计分润时间: {}", date.toString());
		// 查询所有代理
		List<Agent> all = agentService.findAll();
		// 统计所有代理前一天流水
		agentTotalMoneyStatistics(all);
		for (Agent agent : all) {
			// 获取此代理的统计信息
			ProfitStatistics agentStatistics = map.get(Agent.YESTERDAY_PROFIT_STATISTICS_KEY + agent.getId());
			if (agentStatistics != null) {
				// 如果已统计过，更新
				ProfitStatistics agentStatistics2 = profitStatisticsService.findByAgentAndDate(agent, date);
				if (agentStatistics2 != null) {
					agentStatistics.setId(agentStatistics2.getId());
				}
				// 直接分润
				BigDecimal[] parkingLotProfit = getParkingLotProfit(agent);
				// 间接分润
				BigDecimal[] agentProfit = getAgentProfit(agent);
				// 分润比例
				BigDecimal profitProportion = new BigDecimal(agent.getProfitProportion());
				// 保存原始分润 (直接分润+间接分润) 保留两位小数 四舍五入
				agentStatistics.setWeixinOriginalProfit(setScale(parkingLotProfit[0].add(agentProfit[0])));
				agentStatistics.setAlipayOriginalProfit(setScale(parkingLotProfit[1].add(agentProfit[1])));
				agentStatistics.setTotalOriginalProfit(agentStatistics.getWeixinOriginalProfit().add(agentStatistics.getAlipayOriginalProfit()));

				// 原始分润*分润比例 保留两位小数 四舍五入
				agentStatistics.setWeixinProfit(setScale(agentStatistics.getWeixinOriginalProfit().multiply(profitProportion)));
				agentStatistics.setAlipayProfit(setScale(agentStatistics.getAlipayOriginalProfit().multiply(profitProportion)));
				agentStatistics.setTotalProfit(agentStatistics.getWeixinProfit().add(agentStatistics.getAlipayProfit()));
				// 持久化
				profitStatisticsService.update(agentStatistics);
				// 昨天的数据更新redis
				if (DateUtils.diff(date, LocalDate.now()) == 1) {
					redisService.removeString(Agent.YESTERDAY_PROFIT_STATISTICS_KEY + agent.getId());
					redisService.saveString(Agent.YESTERDAY_PROFIT_STATISTICS_KEY + agent.getId(), JSON.toJSONString(agentStatistics), DateUtils.nowToTomorrowSecond());
				}
			}

		}

		// 清除map
		map = null;

	}

	/**
	 * 查询此代理直接分润
	 */
	private BigDecimal[] getParkingLotProfit(Agent agent) {
		// 累加初始值
		BigDecimal weixinProfit = ZERO;
		BigDecimal alipayProfit = ZERO;
		// 查询此代理所有直接车场
		List<ParkingLot> list = parkingLotService.findByAgent(agent.getId());

		for (ParkingLot parkingLot : list) {
			// 查询车场昨日流水
			BigDecimal[] bigDecimals = orderService.countByParkingLotAndPaytime(parkingLot, date);

			// 费率差
			float weixinRate = new BigDecimal(parkingLot.getWeixinRate()).subtract(new BigDecimal(agent.getWeixinRate())).floatValue();
			float alipayRate = new BigDecimal(parkingLot.getAlipayRate()).subtract(new BigDecimal(agent.getAlipayRate())).floatValue();
			// 计算分润 每个车场都给累加起来
			weixinProfit = weixinProfit.add(setScale(bigDecimals[0].multiply(new BigDecimal(weixinRate).divide(HUNDRED))));
			alipayProfit = alipayProfit.add(setScale(bigDecimals[1].multiply(new BigDecimal(alipayRate).divide(HUNDRED))));
		}

		BigDecimal[] bigDecimals = new BigDecimal[2];
		bigDecimals[0] = weixinProfit;
		bigDecimals[1] = alipayProfit;
		return bigDecimals;
	}

	/**
	 * 查询此代理间分润
	 */
	private BigDecimal[] getAgentProfit(Agent agent) {
		BigDecimal weixinProfit = ZERO;
		BigDecimal alipayProfit = ZERO;
		// 查询此代理下所有直接代理
		List<Agent> list = agentRelationService.findChildrenByParent(agent);
		for (Agent agents : list) {
			// 获取子代理流水统计
			ProfitStatistics agentStatistics = map.get(Agent.YESTERDAY_PROFIT_STATISTICS_KEY + agents.getId());
			if (agentStatistics != null) {

				// 费率差 子代理费率-代理费率
				float weixinRate = new BigDecimal(agents.getWeixinRate()).subtract(new BigDecimal(agent.getWeixinRate())).floatValue();
				float alipayRate = new BigDecimal(agents.getAlipayRate()).subtract(new BigDecimal(agent.getAlipayRate())).floatValue();
				// 计算分润
				weixinProfit = weixinProfit.add(agentStatistics.getWeixinMoney().multiply(new BigDecimal(weixinRate).divide(HUNDRED)));
				alipayProfit = alipayProfit.add(agentStatistics.getAlipayMoney().multiply(new BigDecimal(alipayRate).divide(HUNDRED)));
			}
		}

		BigDecimal[] bigDecimals = new BigDecimal[2];
		bigDecimals[0] = weixinProfit;
		bigDecimals[1] = alipayProfit;
		return bigDecimals;
	}

	/**
	 * 统计所有代理前一天的交易流水 存入map中
	 */
	private void agentTotalMoneyStatistics(List<Agent> all) {

		map = new HashMap<>();

		for (Agent agent : all) {
			ProfitStatistics statistics = orderService.countProfitStatisticsByAgent(agent, date);
			// 使用map保存
			map.put(Agent.YESTERDAY_PROFIT_STATISTICS_KEY + agent.getId(), statistics);
		}
	}

	private BigDecimal setScale(BigDecimal n) {
		return SettingUtils.get().setScale(n);
	}
}
